package com.hontech.desktoppastacooker.ui.fragment

import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.Button
import android.widget.EditText
import androidx.fragment.app.Fragment
import com.hontech.bv.conn.serial.Uint16
import com.hontech.desktoppastacooker.R
import com.hontech.desktoppastacooker.conn.Proto
import com.hontech.desktoppastacooker.conn.SerialPortMod
import com.hontech.desktoppastacooker.conn.serial.Uint8
import com.hontech.desktoppastacooker.device.Device
import com.hontech.desktoppastacooker.device.StatusEvent
import com.hontech.desktoppastacooker.ui.view.NumberSensorView
import com.hontech.desktoppastacooker.ui.view.SwitchCtrlView
import com.hontech.desktoppastacooker.ui.view.SwitchSensorView
import com.hontech.desktoppastacooker.ui.window.showErr
import com.hontech.desktoppastacooker.ui.window.showProg
import com.hontech.desktoppastacooker.utils.*
import org.greenrobot.eventbus.Subscribe
import org.greenrobot.eventbus.ThreadMode


class Test1Fragment : Fragment() {

    private lateinit var statusDelegate: StatusDelegate

    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        val view = inflater.inflate(R.layout.fragment_test1, null)
        statusDelegate = StatusDelegate(view.findViewById(R.id.id_test1_parts_sensor))
        DoorDelegate(view.findViewById(R.id.id_test1_parts_door))
        NozzleDelegate(view.findViewById(R.id.id_test1_parts_nozzle))
        return view
    }

    override fun onStop() {
        super.onStop()
        eventBus.unregister(this)
    }

    override fun onStart() {
        super.onStart()
        eventBus.register(this)
    }

    @Subscribe(threadMode = ThreadMode.MAIN_ORDERED)
    fun onStatusEvent(_e: StatusEvent) {
        statusDelegate.update()
    }
}

class Test2Fragment : Fragment() {

    private lateinit var heatDelegate: HeatDelegate

    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        val view = inflater.inflate(R.layout.fragment_test2, null)
        heatDelegate = HeatDelegate(view.findViewById(R.id.id_test2_parts_heat))
        DrawWaterDelegate(view.findViewById(R.id.id_test2_parts_draw))
        return view
    }

    override fun onStop() {
        super.onStop()
        eventBus.unregister(this)
    }

    override fun onStart() {
        super.onStart()
        eventBus.register(this)
    }

    @Subscribe(threadMode = ThreadMode.MAIN_ORDERED)
    fun onStatusEvent(_e: StatusEvent) {
        heatDelegate.update()
    }
}

private class DrawWaterDelegate(view: View) {

    private val etMl = view.findViewById<EditText>(R.id.id_draw_et_ml)
    private val btnDrawTest = view.findViewById<Button>(R.id.id_draw_btn_test)

    private val etDrawTimeout = view.findViewById<EditText>(R.id.id_draw_et_draw_timeout)
    private val btnDrawTimeout = view.findViewById<Button>(R.id.id_draw_btn_draw_timeout_set)

    private val etFlow = view.findViewById<EditText>(R.id.id_draw_et_flow_arg)
    private val btnFlow = view.findViewById<Button>(R.id.id_draw_btn_flow_set)

    private val etPump = view.findViewById<EditText>(R.id.id_draw_et_pump_arg)
    private val btnPump = view.findViewById<Button>(R.id.id_draw_btn_pump_set)

    init {
        btnDrawTest.onClick {
            try {
                val ml = etMl.toInt()
                wrapReq("抽水测试", "",
                    65 * 1000,
                    Proto.REQ_DRAW_WATER_TEST, arrayOf(
                        Uint8(ml)
                    )
                )
            } catch (e: Exception) {
                e.printStackTrace()
            }
        }

        btnDrawTimeout.onClick {
            try {
                val m = etDrawTimeout.toInt()
                wrapReq("设置超时时间", "",
                    3 * 1000,
                    Proto.REQ_DRAW_TIMEOUT_SET, arrayOf(
                        Uint8(m)
                    )
                )
            } catch (e: Exception) {
                e.printStackTrace()
            }
        }

        btnFlow.onClick {

            try {
                val arg = etFlow.toInt()
                wrapReq("设置流量计参数", "",
                    3 * 1000,
                    Proto.REQ_FLOW_SET, arrayOf(
                        Uint16(arg)
                    )
                )
            } catch (e: Exception) {
                e.printStackTrace()
            }
        }

        btnPump.onClick {

            try {
                val arg = etPump.toInt()
                wrapReq("设置电磁泵参数", "",
                    3 * 1000,
                    Proto.REQ_PUMP_ARG_SET, arrayOf(
                        Uint16(arg)
                    )
                )
            } catch (e: Exception) {
                e.printStackTrace()
            }

        }

    }

}

private class HeatDelegate(view: View) {

    private val ctrlSteamHeat = view.findViewById<SwitchCtrlView>(R.id.id_parts_steam_heat)
    private val ctrlWaterHeat = view.findViewById<SwitchCtrlView>(R.id.id_parts_water_heat)
    private val ctrlValve1 = view.findViewById<SwitchCtrlView>(R.id.id_parts_valve1)
    private val ctrlValve2 = view.findViewById<SwitchCtrlView>(R.id.id_parts_valve2)
    private val ctrlValve3 = view.findViewById<SwitchCtrlView>(R.id.id_parts_valve3)
    private val ctrlValve4 = view.findViewById<SwitchCtrlView>(R.id.id_parts_valve4)
    private val steamPump = view.findViewById<SwitchCtrlView>(R.id.id_parts_steam_pump)
    private val waterPump = view.findViewById<SwitchCtrlView>(R.id.id_parts_water_pump)
    private val outletPump = view.findViewById<SwitchCtrlView>(R.id.id_parts_outlet_pump)

    private val drawState = view.findViewById<NumberSensorView>(R.id.id_parts_num_draw)
    private val heatState = view.findViewById<NumberSensorView>(R.id.id_parts_num_heat)
    private val btnHeatReset = view.findViewById<Button>(R.id.id_parts_btn_heat_reset)
    private val btnHeatStop = view.findViewById<Button>(R.id.id_parts_btn_heat_stop)
    private val btnDrawReset = view.findViewById<Button>(R.id.id_parts_btn_draw_reset)
    private val btnDrawStop = view.findViewById<Button>(R.id.id_parts_btn_draw_stop)

    private val etHeatTimeout = view.findViewById<EditText>(R.id.id_parts_et_heat_timeout)
    private val etHeatTemp = view.findViewById<EditText>(R.id.id_parts_et_heat_temp)
    private val etHeatKpa = view.findViewById<EditText>(R.id.id_parts_et_heat_kpa)
    private val btnHeatSet = view.findViewById<Button>(R.id.id_parts_btn_heat_set)
    private val btnQuery = view.findViewById<Button>(R.id.id_parts_btn_query)

    private suspend fun partsCtrl(id: Int, v: Boolean) {
        val value = if (v) 0 else 1
        val title = when (id) {
            1 -> "蒸汽加热器"
            2 -> "开水加热器"
            3 -> "电磁阀1"
            4 -> "电磁阀2"
            5 -> "电磁阀3"
            6 -> "电磁阀4"
            7 -> "蒸汽水泵"
            8 -> "开水水泵"
            9 -> "废水泵"
            else -> "未知"
        }
        val msg = when (value) {
            0 -> "打开"
            1 -> "关闭"
            else -> "未知"
        }
        ctrl(title, msg, 3000, Proto.REQ_PARTS_CTRL, arrayOf(Uint8(id), Uint8(value)))
    }

    init {
        btnHeatSet.onClick {

            try {
                val timeout = etHeatTimeout.toInt()
                val temp = etHeatTemp.toInt()
                val kpa = etHeatKpa.toInt()
                wrapReq("加热参数设置", "", 3000, Proto.REQ_HEAT_ARG_SET, arrayOf(
                    Uint8(timeout),
                    Uint16(temp),
                    Uint16(kpa)
                ))
            } catch (e: Exception) {
                e.printStackTrace()
            }
        }

        btnQuery.onClick {

            val dialog = showProg("查询参数", "")

            try {
                val ret = SerialPortMod.query(Proto.QUERY_ARG)
                val drawTimeout = Uint8()
                val heatTimeout = Uint8()
                val temp = Uint16()
                val kpa = Uint16()
                val flow = Uint16()
                val pump = Uint16()
                val adc = Uint16()
                ret.parse(arrayOf(
                    drawTimeout,
                    heatTimeout,
                    temp,
                    kpa,
                    flow,
                    pump,
                    adc
                ))
                dialog.showSuccess("查询成功",
                    "抽水超时时间 ${drawTimeout.value}分钟\r\n" +
                            "加热超时时间 ${heatTimeout.value}分钟\r\n" +
                            "蒸汽温度设定值 ${temp.value}℃\r\n" +
                            "蒸汽压力设定值 ${kpa.value}℃\r\n" +
                            "流量计参数 ${flow.value}\r\n" +
                            "电磁泵参数 ${pump.value}\r\n" +
                            "门堵转电流adc ${adc.value}")
            } catch (e: Exception) {
                e.printStackTrace()
                dialog.error(e)
            }

        }

        btnDrawReset.onClick {
            wrapReq("抽水控制", "重启",
                3000,
                Proto.REQ_DRAW_HEAT_CTRL,
                arrayOf(Uint8(0))
            )
        }
        btnDrawStop.onClick {
            wrapReq("抽水控制", "停止",
                3000,
                Proto.REQ_DRAW_HEAT_CTRL,
                arrayOf(Uint8(1))
            )
        }

        btnHeatReset.onClick {
            wrapReq("加热控制", "重启",
            3000, Proto.REQ_DRAW_HEAT_CTRL,
            arrayOf(Uint8(2))
            )
        }

        btnHeatStop.onClick {
            wrapReq("加热控制", "停止",
            3000, Proto.REQ_DRAW_HEAT_CTRL,
            arrayOf(Uint8(3))
            )
        }

        ctrlSteamHeat.clickCb = {
            partsCtrl(1, it)
        }
        ctrlWaterHeat.clickCb = {
            partsCtrl(2, it)
        }
        ctrlValve1.clickCb = {
            partsCtrl(3, it)
        }
        ctrlValve2.clickCb = {
            partsCtrl(4, it)
        }
        ctrlValve3.clickCb = {
            partsCtrl(5, it)
        }
        ctrlValve4.clickCb = {
            partsCtrl(6, it)
        }
        steamPump.clickCb = {
            partsCtrl(7, it)
        }
        waterPump.clickCb = {
            partsCtrl(8, it)
        }
        outletPump.clickCb = {
            partsCtrl(9, it)
        }
    }

    fun update() {
        val status = Device.status
        ctrlSteamHeat.set(status.isSteamHeatOpen())
        ctrlWaterHeat.set(status.isWaterHeatOpen())
        ctrlValve1.set(status.isValve1Open())
        ctrlValve2.set(status.isValve2Open())
        ctrlValve3.set(status.isValve3Open())
        ctrlValve4.set(status.isValve4Open())
        steamPump.set(status.isSteamPumpOpen())
        waterPump.set(status.isWaterPumpOpen())
        outletPump.set(status.isOutletPumpOpen())
        drawState.set( status.drawState() )
        heatState.set(status.heatState())
    }
}

private class StatusDelegate(view: View) {

    private val numVersion = view.findViewById<NumberSensorView>(R.id.id_test_num_version)
    private val nozzleTop = view.findViewById<SwitchSensorView>(R.id.id_test_sw_nozzle_top)
    private val nozzleAlm = view.findViewById<SwitchSensorView>(R.id.id_test_sw_nozzle_alm)
    private val leak = view.findViewById<SwitchSensorView>(R.id.id_test_sw_leak)
    private val doorFront = view.findViewById<SwitchSensorView>(R.id.id_test_sw_door_front)
    private val doorBack = view.findViewById<SwitchSensorView>(R.id.id_test_sw_door_back)
    private val near = view.findViewById<SwitchSensorView>(R.id.id_test_sw_near)
    private val steamHigh = view.findViewById<SwitchSensorView>(R.id.id_test_sw_steam_high)
    private val steamLow = view.findViewById<SwitchSensorView>(R.id.id_test_sw_steam_low)
    private val flow = view.findViewById<NumberSensorView>(R.id.id_test_num_flow)
    private val kpa = view.findViewById<NumberSensorView>(R.id.id_test_num_kpa)
    private val steam = view.findViewById<NumberSensorView>(R.id.id_test_num_steam)
    private val adc = view.findViewById<NumberSensorView>(R.id.id_test_num_adc)

    fun update() {
        val status = Device.status
        numVersion.set(status.versionString())
        nozzleTop.set(status.isNozzleTop())
        nozzleAlm.set(status.isNozzleAlm())
        leak.set(status.isLeak())
        doorFront.set(status.isDoorFront())
        doorBack.set(status.isDoorBack())
        near.set(status.isNear())
        steamHigh.set(status.isSteamHigh())
        steamLow.set(status.isSteamLow())
        flow.set(status.flowCount.value)

        if (status.isSteamOk()) {
            steam.set(status.steam())
        } else {
            steam.set("异常")
        }

        kpa.set(status.kpa())
        adc.set(status.adc.value)
    }
}

private class DoorDelegate(view: View) {

    private val btnDoorOpen = view.findViewById<Button>(R.id.id_test_btn_door_open)
    private val btnDoorClose = view.findViewById<Button>(R.id.id_test_btn_door_close)
    private val btnSet = view.findViewById<Button>(R.id.id_test_btn_door_adc_set)
    private val etAdc = view.findViewById<EditText>(R.id.id_test_et_motor_adc)

    init {

        btnSet.onClick {

            try {
                val adc = etAdc.toInt()

                wrapReq(
                    "设置",
                    "门电机堵转电流adc:${adc}",
                    3000,
                    Proto.REQ_DOOR_ADC_SET,
                    arrayOf(Uint16(adc))
                )

            } catch (e: Exception) {
                e.printStackTrace()
            }

        }

        btnDoorOpen.onClick {

            if (!Device.status.isNozzleTop()) {
                showErr("警告", "喷嘴不在零点")
                return@onClick
            }

            wrapReq(
                "门控制",
                "门打开",
                30 * 1000,
                Proto.REQ_DOOR_CTRL,
                arrayOf(Uint8(0))
            )
        }

        btnDoorClose.onClick {

            if (!Device.status.isNozzleTop()) {
                showErr("警告", "喷嘴不在零点")
                return@onClick
            }

            wrapReq(
                "门控制",
                "门关闭",
                30 * 1000,
                Proto.REQ_DOOR_CTRL,
                arrayOf(Uint8(1))
            )
        }
    }


}

private class NozzleDelegate(view: View) {

    private val etDistance = view.findViewById<EditText>(R.id.id_nozzle_et_distance)
    private val btnCtrl = view.findViewById<Button>(R.id.id_nozzle_btn_ctrl)
    private val btnReset = view.findViewById<Button>(R.id.id_nozzle_btn_reset)

    init {

        btnCtrl.onClick {
            try {
                val distance = etDistance.toInt()
                wrapReq("喷嘴控制", "",
                    20 * 1000,
                    Proto.REQ_NOZZLE_CTRL, arrayOf(
                        Uint16(distance)
                    )
                )
            } catch (e: Exception) {
                e.printStackTrace()
            }
        }

        btnReset.onClick {
            wrapReq("喷嘴控制", "复位",
            20 * 1000,
                Proto.REQ_NOZZLE_CTRL,
                arrayOf(Uint16(0)))
        }
    }


}

